Categories
discuss

Populate TableLayout with android:layout_weight programmatically

I am trying to populate a tablelayout with cells and rows stretches to fill the whole screen. Like this:

http://imageshack.us/photo/my-images/69/device20120201005942.png/

This layout designed in Graphical Layout window in Eclipse gives what I want (android:layout_weight solves vertical stretching):

<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_gravity="center"
    android:stretchColumns="*" >

    <TableRow
        android:id="@+id/tableRow1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center" android:layout_weight="1">

        <ImageView
            android:id="@+id/imageView1"
            android:layout_gravity="center"
            android:src="@drawable/add" />
        <ImageView
            android:id="@+id/imageView2"
            android:layout_gravity="center"
            android:src="@drawable/bound" />
        <ImageView
            android:id="@+id/imageView3"
            android:layout_gravity="center"
            android:src="@drawable/cod" />
    </TableRow>

    <TableRow
        android:id="@+id/tableRow2"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_weight="1" >

    <ImageView
        android:id="@+id/imageView4"
        android:layout_gravity="center"
        android:src="@drawable/delete" />
    <ImageView
        android:id="@+id/imageView5"
        android:layout_gravity="center"
        android:src="@drawable/delete2" />
    <ImageView
        android:id="@+id/imageView6"
        android:layout_gravity="center"
        android:src="@drawable/floppy" />
    </TableRow>
</TableLayout>

I am trying to create the same look within code but failed so far. Here is the oncreate of my Activity:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.tablelo);

    TableLayout tl = (TableLayout) findViewById(R.id.table);
    Log.d(TAG, "Width :" + tl.getWidth());
    for (int row = 0; row < 3; row++) {
        TableRow tr = new TableRow(this);
        tr.setId(100 + row);

        for (int cell = 0; cell < 3; cell++) {
            ImageView image = new ImageView(this);
            image.setImageResource(imageIDs[row * 3 + cell]);
            tr.addView(image);
        }

        tr.setGravity(Gravity.CENTER);
        LayoutParams params = new TableRow.LayoutParams(
                LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT, 1);

        tr.setLayoutParams(params);

        tl.addView(tr, params);
    }
    tl.setStretchAllColumns(true);
}

I am missing the code to set ImageView gravity, but this attemp causes crash:

image.setLayoutParams(new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, Gravity.CENTER));

This code results 3 rows created, each stretch horizontally but not vertically:

http://imageshack.us/photo/my-images/835/gridc.png/

I can not find what I am missing here. I also tried to prepare a tablerow in designer and inflate and add to table during runtime but result did not change.

So, somehow, I want to get programmatically the same layout that I could created with editor .

Help, please!

Answer

I’ve spent an hour and a half trying to figure out what was going on. And then I found it 🙂 Here’s a complete listing of my TableActivity, please note the usage of different LayoutParams for table rows and images:

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.widget.*;
import android.widget.TableLayout;
import android.widget.TableRow;

public class TableActivity extends Activity {

    private static final String TAG="TableActivity";

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.table_activity);

        TableLayout tl = (TableLayout) findViewById(R.id.table);
        Log.d(TAG, "Width :" + tl.getWidth());

        for (int row = 0; row < 3; row++) {
            TableRow tr = new TableRow(this);
            tr.setId(100 + row);

            //Note that you must use TableLayout.LayoutParams, 
            //since the parent of this TableRow is a TableLayout
            TableLayout.LayoutParams params = new TableLayout.LayoutParams(
                    TableLayout.LayoutParams.WRAP_CONTENT, TableLayout.LayoutParams.WRAP_CONTENT, 1f);

            for (int cell = 0; cell < 3; cell++) {
                ImageView image = new ImageView(this);
                image.setImageResource(android.R.drawable.btn_plus);
                //Note that here you must use TableRow.LayoutParams
                //since TableRow is the parent of this ImageView
                TableRow.LayoutParams imageParams = new TableRow.LayoutParams();

                //And this is how you set the gravity:
                imageParams.gravity = Gravity.CENTER;
                image.setLayoutParams(imageParams);
                tr.addView(image);
            }
            tr.setLayoutParams(params);
            tl.addView(tr, params);
        }
        tl.setStretchAllColumns(true);
    }
}

table_activity.xml is just an empty table layout:

<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
         android:id="@+id/table"
          android:layout_width="match_parent"
          android:layout_height="match_parent">
</TableLayout>

So to put it short, the simplest solution would be to use layouts defined in xml files 🙂 But if you have to use JAVA, you must be careful with what king of LayoutParams you are using, you should always use the one of a view’s parent.

Categories
discuss

Spring Batch Multi Threading – How to make each thread read unique records?

This question has been asked a lot of times in many forums. But I don’t see an answer that fits me. I am trying to implement Multi-threaded Step in my spring batch implementation.

  1. Have a staging table with 100k records

  2. Want to process it in 10 threads of commit interval 300 per thread- so 3000 records at any point of time.

  3. I defined a task executor and referred it inside the step i wanted to multi thread

  4. My idea is that first I would get the thread pool size (10) and update the thread_id column with a velue(can be 1-10) to each of the 100k records. In this case of 10 threads and 100k records so 10k records will be assigned one id – I am trying to implement a stagingsteplistener to do this.

  5. wrote a reader for this staging table. task executor will create 10 readers and each reader must read 300 different records and process them – Now how do I pass a common id between the step listener and reader so that each thread will have its own set of records to process.

As of now I have only one JVM. So I am thinking of doing this in Multi Threaded step itself rather than thinking about partition based approach.

Please help……

I referred pro spring batch book and created a staging step listener which is accepting a run id from the job configuration xml using job parameters as below

<beans:bean id="stagingStepListener"
class="com.apress.springbatch.statement.listener.StagingStepListener" scope="step">
<beans:property name="dataSource" ref="dataSource"/>
<beans:property name="tableName" value="transaction"/>
<beans:property name="whereClause"
value="where jobId is null and processed is null"/>
<beans:property name="jobId" value="#{jobParameters[run.id]}"/>
</beans:bean>

What i dont find is this? From where is this “run.id” coming from. I dont see that in any place in the book. I copied the same implementation in my spring batch and when i run it I see exception saying that run.id is not identifiable. Please help me about how to do this?

Answer


  • What i dont find is this? From where is this “run.id” coming from

JobParameters

This is just a parameter that you pass to jobParameters. Usually a different run.id (a conventional name) for each instance is used because the framework has no way of knowing what changes to the JobParameters make it the “next” job instance.

You can pass this “run.id” to the jobParameters as:

new JobParametersBuilder().addLong("run.id", 1L).toJobParameters()

take a look at the JobParametersIncrementer‘s documentation for more details.


  • how do I pass a common id between the step listener and reader so that each thread will have its own set of records to process

Don’t

This is quite a dangerous route, since many participants in a Step (e.g. readers and writers) are stateful, and if the state is not segregated by thread, then those components are not usable in a multi-threaded Step. In particular most of the off-the-shelf readers and writers from Spring Batch are not designed for multi-threaded use.

Partitioning

I would recommend to use Partitioning. It is a lot simpler than it seems, and you can still utilize multiple threads for it. Take a look at the sample batch jobs that use partitioning, which comes from “Spring Batch samples” is there to:

show multi-threaded step execution using the PartitionHandler SPI. The example uses a TaskExecutorPartitionHandler to spread the work of reading some files acrosss multiple threads, with one Step execution per thread. The key components are the PartitionStep and the MultiResourcePartitioner which is responsible for dividing up the work. Notice that the readers and writers in the Step that is being partitioned are step-scoped, so that their state does not get shared across threads of execution.

Categories
discuss

JNI on Android: How to retrieve a string from Java code?

I read a lot of examples to retrieve a java string in C/C++ code, but it seems that I miss something. this simple code doesn’t work..

In ActivityTest (android java code) I’ve:

public static native void nativeInit(String stringfromjava);

In TestActivity I’ve:

ActivityTest.nativeInit("test");

and in my test-jni.c:

JNIEXPORT void JNICALL  Java_com_test_jni_ActivityTest_nativeInit(JNIEnv* env, jclass cls, jobject obj, jstring stringfromjava){

__android_log_print(ANDROID_LOG_INFO, "TESTJNI","Native Init started");

const char* w_buf = (*env)->GetStringUTFChars(env, stringfromjava, 0);

if(w_buf == NULL) {
    __android_log_print(ANDROID_LOG_INFO, "TESTJNI","file path recv nothing");
}

else {
        __android_log_print(ANDROID_LOG_INFO, "TESTJNI","String: %s", w_buf);
}

(*env)->ReleaseStringUTFChars(env, stringfromjava, w_buf);

}

But in my logcat I get only:

I/TESTJNI (18921): Native Init started
I/TESTJNI (18921): String: 

Where I’m wrong…?

FIXED Thanks to Mario, removing “jobject obj” from the signature fixed my issue!

Answer

Only wrote one short test so far (similar to your program), but my function had a bit different signature (might depend on SDK/NDK/JDK version? took it from some tutorial code I found):

extern "C" void Java_com_whatever_Activity_method(JNIEnv* env, jobject jthis, jstring param);

Obviously you won’t need extern "C" if you’re not writing C++.

The Java signature would be:

native void method(String param);

Edit:

To obtain the string (not sure if this is 100% correct, but it works):

const char *cparam = env->GetStringUTFChars(param, 0);
// .. do something with it
env->ReleaseStringUTFChars(param, cparam);

Open to suggestions in case there’s something wrong in there. It works fine, but might still be some issue, so feel free to comment.

Categories
discuss

Android: stopService doesn’t call onDestroy

I have big problems with stopping a service, which plays audio file. I want to stop the current service before I play another file.

Activity:

public void playTrack(View view){       
    Intent i=new Intent(this,playService.class);
    i.setAction("com.c0dehunterstudios.relaxer.PLAY");
    
    if(isPlaying){ 
          stopService(i);   
          isPlaying=false;
          Log.v("ACTIVITY", "Stopping..");
    }
    
    startService(i);
    isPlaying=true;
}

Service:

@Override
public void OnDestroy(){
    Log.v("SERVICE","Service killed");
    player.stop();
    super.onDestroy();  
}

But sadly it doesn’t work – actually it doesn’t even come down to the “Service killed” inside OnDestroy().

What am I doing wrong?

Answer

First, it’s onDestroy, not OnDestroy . Second, you must use the @Override annotation for compile-time checking, so your Service code should look somewhat like this:

@Override
public void onDestroy(){
    Log.v("SERVICE","Service killed");
    player.stop();
    super.onDestroy();  
}
Categories
discuss

Cross domain issue with iframes

I know the solutions for cross browser domain calls. Either use JSONP, do a proxy call, or accept domains on server. I found 1 more strange way today at my company.

Method:

They are changing the host to match the host of second server by using this –

window.location.host = "xyz.com";
          or
document.domain = "xyz.com";

Then they are creating a hidden iframe and getting contents in iframe and replacing contents to visible element.

Problem:

It works with iframe but if I do ajax call, it doesn’t work. Any words on this?

Answer

i’m not a fan of jsonp, it creates coupling between data and presentation, and so i researched this issue before, and well, there’s a trick that you can use, follow this:

let’s say we have the main window named A and the “child” window in the iframe named B. A and B must be served from the same host, but can have different subdomains, something like:

A is served from sub1.example.com

B is served from sub2.example.com

browsers will let you change the domain of the document, but still restrict you on that, so you can only change the domain by removing subdomains until you reach the host, and so in A you change the domain, like so:

document.domain = "example.com";

in B you first make an ajax call to its domain (sub2.example.com), then after the first request was sent you change the domain just like in A, so that both documents have the same domain. since you made a request to the original domain in B the browser will allow you to keep sending requests to it, but since you also changed its domain, and now A and B have the same domain they can communicate with each other.

it’s important that you first make at least one request in B to its original domain, before you change the domain. also, it won’t work if both pages are not served from the same host, so in most cases it does not solve the problem, but it does allow you a bit more room to maneuver.

i used this trick more than once and haven’t came across any problems, as far as i’m aware, it works in all browsers, let me know if it doesn’t in some cases.

here’s a pseudo example:

in A
==================
document.domain = "example.com";
var child; // keep reference to B
function setChild(win) {
    childDocument = win;
}

function handleMessage(message) {
    do what ever it is you need to
}

in B
==================
make ajax request
document.domain = "example.com";
parent.setChild(this);

function ajaxCallback(message) {
    parent.handleMessage(message);
}
Source: stackoverflow
Text is available under the Creative Commons Attribution-ShareAlike License; additional terms may apply. By using this site, you agree to the Privacy Policy, and Copyright Policy. Content is available under CC BY-SA 3.0 unless otherwise noted. The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 © No Copyrights, All Questions are retrived from public domain..