6

AndroidデバイスからGoogleクラウドプリントを使用して静かに印刷できるかどうか教えてもらえますか? 目標は、私のアプリが URL または SD カードからファイルを取得し、それを特定のプリンターに送信することです。画面を見たり、何かに触れたりする必要はありません。実際には、Bluetooth 接続デバイスのバーコード スキャンによってトリガーされます。

ありがとう

4

3 に答える 3

5

それは可能ですが、なぜドキュメントにあまり情報がないのかわかりません...

トリッキーな部分は、Android デバイスのみを使用して Google クラウド プリント API に接続することです (ドキュメントで説明されているように、サード パーティのサーバーは使用しません: https://developers.google.com/cloud-print/docs/appDevGuide )。説明します。

まず、アプリに Google サインイン API を含める必要があります。firebase API をお勧めしますhttps://firebase.google.com/docs/auth/android/google-signin

次に、Google API コンソールに移動する必要があります:メニューのhttps://console.developers.google.com資格情報に移動してOAuth 2.0 クライアント IDまでスクロールし、Web クライアント (Google サービスによって自動作成)を選択して、プロジェクトに保存します。クライアント IDクライアント シークレットキー...私のプロジェクトでは、以下のコードに示すように、 " gg_client_web_id " と " gg_client_web_secret " として保存しました。

次に、すべてのコードを貼り付けてから説明します。

public class MainActivity extends AppCompatActivity
    implements GoogleApiClient.OnConnectionFailedListener {
private GoogleApiClient mGoogleApiClient;
private FirebaseAuth mAuth;
private FirebaseAuth.AuthStateListener mAuthListener;
private static final int REQUEST_SINGIN = 1;
private TextView txt;
public static final String TAG = "mysupertag";
public static final String URLBASE = "https://www.google.com/cloudprint/";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    txt = (TextView) findViewById(R.id.txt);
    mAuth = FirebaseAuth.getInstance();
    // Configure Google Sign In
    GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestIdToken(getString(R.string.gg_client_web_id))
            .requestEmail()
            .requestServerAuthCode(getString(R.string.gg_client_web_id))
            .requestScopes(new Scope("https://www.googleapis.com/auth/cloudprint"))
            .build();
    mGoogleApiClient = new GoogleApiClient.Builder(this)
            .enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
            .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
            .build();

    findViewById(R.id.sign_in_button).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            signIn();
        }
    });

    mAuthListener = new FirebaseAuth.AuthStateListener() {
        @Override
        public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
            FirebaseUser user = firebaseAuth.getCurrentUser();
            if (user != null) {
                // User is signed in
                Log.d(TAG, "onAuthStateChanged:signed_in:" + user.getUid());
            } else {
                // User is signed out
                Log.d(TAG, "onAuthStateChanged:signed_out");
            }
            // ...
        }
    };
}

@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
    Log.d(TAG, "error connecting: " + connectionResult.getErrorMessage());
    Toast.makeText(this, "error CONN", Toast.LENGTH_LONG).show();
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
    if (requestCode == REQUEST_SINGIN) {
        GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
        if (result.isSuccess()) {
            // Google Sign In was successful, authenticate with Firebase
            GoogleSignInAccount account = result.getSignInAccount();
            firebaseAuthWithGoogle(account);
        } else {
            // Google Sign In failed, update UI appropriately
            // ...
            Toast.makeText(this, "error ", Toast.LENGTH_LONG).show();
        }
    }
}

private void signIn() {
    Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
    startActivityForResult(signInIntent, REQUEST_SINGIN);
}

@Override
public void onStart() {
    super.onStart();
    mAuth.addAuthStateListener(mAuthListener);
}

@Override
public void onStop() {
    super.onStop();
    if (mAuthListener != null) {
        mAuth.removeAuthStateListener(mAuthListener);
    }
}

private void firebaseAuthWithGoogle(final GoogleSignInAccount acct) {
    Log.d(TAG, "firebaseAuthWithGoogle:" + acct.getId());

    AuthCredential credential = GoogleAuthProvider.getCredential(acct.getIdToken(), null);
    mAuth.signInWithCredential(credential)
            .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull Task<AuthResult> task) {
                    Log.d(TAG, "signInWithCredential:onComplete:" + task.isSuccessful());

                    // If sign in fails, display a message to the user. If sign in succeeds
                    // the auth state listener will be notified and logic to handle the
                    // signed in user can be handled in the listener.
                    FirebaseUser user = task.getResult().getUser();
                    txt.setText(user.getDisplayName() + "\n" + user.getEmail());//todo
                    if (!task.isSuccessful()) {
                        Log.w(TAG, "signInWithCredential", task.getException());
                        Toast.makeText(MainActivity.this, "Authentication failed.",
                                Toast.LENGTH_SHORT).show();
                    }
                    getAccess(acct.getServerAuthCode());
                }
            });
}

private void getPrinters(String token) {
    Log.d(TAG, "TOKEN: " + token);
    String url = URLBASE + "search";
    Ion.with(this)
            .load("GET", url)
            .addHeader("Authorization", "Bearer " + token)
            .asString()
            .withResponse()
            .setCallback(new FutureCallback<Response<String>>() {
                @Override
                public void onCompleted(Exception e, Response<String> result) {
                    Log.d(TAG, "finished " + result.getHeaders().code() + ": " +
                            result.getResult());
                    if (e == null) {
                        Log.d(TAG, "nice");
                    } else {
                        Log.d(TAG, "error");
                    }
                }
            });
}

private void getAccess(String code) {
    String url = "https://www.googleapis.com/oauth2/v4/token";
    Ion.with(this)
            .load("POST", url)
            .setBodyParameter("client_id", getString(R.string.gg_client_web_id))
            .setBodyParameter("client_secret", getString(R.string.gg_client_web_secret))
            .setBodyParameter("code", code)
            .setBodyParameter("grant_type", "authorization_code")
            .asString()
            .withResponse()
            .setCallback(new FutureCallback<Response<String>>() {
                @Override
                public void onCompleted(Exception e, Response<String> result) {
                    Log.d(TAG, "result: " + result.getResult());
                    if (e == null) {
                        try {
                            JSONObject json = new JSONObject(result.getResult());
                            getPrinters(json.getString("access_token"));
                        } catch (JSONException e1) {
                            e1.printStackTrace();
                        }
                    } else {
                        Log.d(TAG, "error");
                    }
                }
            });
}}

ご覧のとおり、onCreate で重要な部分は、Google クラウド プリント スコープを使用してGoogleSignInOptionsを作成し、requestIdToken/ requestServerAuthCodeメソッドを呼び出すことです。

次に、firebaseAuthWithGoogleメソッドでgetAccessメソッドを呼び出してOAuth アクセス トークンを取得し、Ion ライブラリを使用しているすべてのリクエストを作成します: https://github.com/koush/ion

次に、access_token を使用して、Google クラウド プリント API へのリクエストを実行できます。この場合、getPrintersメソッドを呼び出します。このメソッドでは、(Google クラウド プリント API から)「検索」メソッドを呼び出して、に関連付けられているすべてのプリンターを取得します。サインインした Google アカウント.. (プリンターを Google アカウントに関連付けるには、https ://support.google.com/cloudprint/answer/1686197?hl=en&p=mgmt_classic にアクセスしてください) .addHeader("Authorization" 、「ベアラー」 + トークン)、これはリクエストの重要な部分です。「トークン」var は access_token です。APIを使用するには、この Authorization ヘッダーを追加する必要があり、有効期限が切れたら更新することを忘れないでください。ここで説明:https://developers.google.com/identity/protocols/OAuth2ForDevicesの「更新トークンの使用」部分。

これで、Google クラウド プリント API の「submit」メソッドに POST リクエストを送信して何かを印刷できるようになりまし。利用可能なすべてのメソッドとそれらの使用方法を参照してください (パラメーターがそれらに送信されるなど)。もちろん、そのリンクでは「送信」方法についても説明しています。

編集:

ION ライブラリと MJSON ライブラリを使用して印刷するために「/submit」にリクエストを送信する方法の例 ( https://bolerio.github.io/mjson/ ) MJSON は JSON オブジェクトを作成するためのものです。好む

private void printPdf(String pdfPath, String printerId) {
    String url = URLBASE + "submit";
    Ion.with(this)
            .load("POST", url)
            .addHeader("Authorization", "Bearer " + YOUR_ACCESS_TOKEN)
            .setMultipartParameter("printerid", printerId)
            .setMultipartParameter("title", "print test")
            .setMultipartParameter("ticket", getTicket())
            .setMultipartFile("content", "application/pdf", new File(pdfPath))
            .asString()
            .withResponse()
            .setCallback(new FutureCallback<Response<String>>() {
                @Override
                public void onCompleted(Exception e, Response<String> result) {
                    if (e == null) {
                        Log.d(TAG, "PRINTTT CODE: " + result.getHeaders().code() +
                                ", RESPONSE: " + result.getResult());
                        Json j = Json.read(result.getResult());
                        if (j.at("success").asBoolean()) {
                            Toast.makeText(MainActivity.this, "Success", Toast.LENGTH_LONG).show();
                        } else {
                            Toast.makeText(MainActivity.this, "ERROR", Toast.LENGTH_LONG).show();
                        }
                    } else {
                        Toast.makeText(MainActivity.this, "ERROR", Toast.LENGTH_LONG).show();
                        Log.d(TAG, e.toString());
                    }
                }
            });
}

private String getTicket() {
    Json ticket = Json.object();
    Json print = Json.object();
    ticket.set("version", "1.0");

    print.set("vendor_ticket_item", Json.array());
    print.set("color", Json.object("type", "STANDARD_MONOCHROME"));
    print.set("copies", Json.object("copies", 1));

    ticket.set("print", print);
    return ticket.toString();
}
于 2016-10-18T11:57:35.747 に答える
2

はい、この REST API ( https://www.google.com/cloudprint/submit ) を使用してサイレント印刷を実現できます。WCF サービスを使用して実行しました。URL から base64 コンテンツとしてコンテンツをダウンロードし、追加する必要があります

contentType=dataUrl

リクエストで。これがコードです..

                postData = "printerid=" + PrinterId;
                postData += "&title=" + JobTitle;
                postData += "&ticket=" + ticket;
                postData += "&content=data:" + documentContent.ContentType + ";base64," + documentContent.Base64Content;
                postData += "&contentType=dataUrl";
                postData += "&tag=test";

次に、この方法で REST API を送信するリクエストを作成してください。

     var request = (HttpWebRequest)WebRequest.Create("https://www.google.com/cloudprint/submit");
     var data = Encoding.ASCII.GetBytes(postData);
            request.Headers.Add("Authorization: Bearer " + Token);
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";
            request.ContentLength = data.Length;
            request.UseDefaultCredentials = true;

            using (var stream = request.GetRequestStream())
            {
                stream.Write(data, 0, data.Length);
            }
            var response = (HttpWebResponse)request.GetResponse();
            string responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
            JavaScriptSerializer json_serializer = new JavaScriptSerializer();
            PrintJobResponse printInfo = json_serializer.Deserialize<PrintJobResponse>(responseString);
            return printInfo;

ありがとう。

于 2016-03-07T06:27:35.580 に答える